<template>
  <component
    :is="!useVirtual ? 'el-select' : 'el-select-v2'"
    ref="autocompleteRef"
    :popper-class="popperClassStr"
    v-model="childSelectedValue"
    :options="!useVirtual ? null : optionsTemp"
    :style="{ width: width || '100%' }"
    :filter-method="remote ? remoteMethod : filterMethod || changeValue"
    :remote-method="remoteMethod ? remoteMethod : customRemoteMethod"
    :filterable="filterable"
    :suffix-icon="filterable || remote ? Search : ArrowDown"
    :value-on-clear="() => ''"
    @change="handleChange"
    v-on="$attrs"
    v-bind="{
      clearable: true,
      multiple: multiple,
      disabled: disabled,
      searchable: false,
      remote: remote,
      ...$attrs,
    }"
  >
    <!-- <template v-for="(index, name) in slots" v-slot:[name]="data">
      <slot :name="name" v-bind="data" />
    </template> -->
    <template #empty>
      <div v-if="searchable" class="t_select__wrap">
        <el-input @input="changeValue" v-model="keyword" placeholder="请输入搜索内容" clearable></el-input>
        <el-divider />
        <div>暂无数据</div>
      </div>
    </template>
    <template v-if="!useVirtual && optionsTemp && optionsTemp.length">
      <div v-if="searchable" class="t_select__wrap">
        <el-input @input="changeValue" v-model="keyword" placeholder="请输入搜索内容" clearable></el-input>
        <el-divider />
      </div>
      <el-option
        v-for="(item, index) in optionsTemp"
        :key="index + 'i'"
        :label="item[optionsProps.label]"
        :value="item[optionsProps.value]"
        :disabled="item[optionsProps.disabled]"
      >
        <!-- <slot name="option" :scope="item">{{ item[optionsProps.label] }}</slot> -->
        <slot name="option" :scope="item">
          <span v-if="Array.isArray(displayKey) && displayKey.length > 1">
            <span v-for="(itemValue, index) in displayKey" :key="index"
              >{{ item[itemValue] }}
              <span v-if="index < displayKey.length - 1">&nbsp;</span>
            </span>
          </span>
          <span v-else>{{ item[optionsProps.label] }}</span>
        </slot>
      </el-option>
      <div class="fi_select__bottom-loading">
        <el-icon v-if="!loadMoreEndTemp && usePagination" class="is-loading">
          <Loading color="#666" />
        </el-icon>
        <div v-if="loadMoreEndTemp && usePagination" class="fi_select__bottom-loading-text">--- 已经到底啦 ---</div>
      </div>

      <!-- <div v-if="multiple && !isShowPagination" class="t_select__wrap">
        <el-divider />
        <el-checkbox v-model="selectChecked" @change="selectAll" class="all_checkbox">全选</el-checkbox>
      </div> -->
      <div class="t_select__wrap" v-if="isShowPagination">
        <el-divider />
        <el-pagination
          v-model:current-page="paginationOption.currentPage"
          v-model:page-size="paginationOption.pageSize"
          :layout="paginationOption.layout || 'total, prev, pager, next, jumper'"
          :pager-count="paginationOption.pagerCount"
          :total="paginationOption.total"
          v-bind="{
            small: true,
            background: true,
            ...$attrs,
            ...paginationOption.bind,
          }"
        />
      </div>
    </template>
  </component>
</template>

<script lang="ts">
import { ElSelect, ElSelectV2 } from 'element-plus'
import { Loading, Search, ArrowDown } from '@element-plus/icons-vue'
import _ from 'lodash'

export default {
  components: {
    ElSelect,
    ElSelectV2,
  },
}
</script>

<script setup lang="ts">
import { computed, useSlots, watch, PropType, ref, onMounted, onUnmounted, reactive } from 'vue'
import { apiQueryCodeitem } from '@/api/common'
import type { OptionsProps, SelectItem } from './select'
import type { CodeOption } from '@/types/components'
import { useRoute } from 'vue-router'
import { apiRequestPost } from '@/api/globalApi.js'
import _ from 'lodash'

const route = useRoute()

const selectProps = defineProps({
  popperClass: {
    type: String,
    default: 'fi-select-popper-class',
  },
  modelValue: {
    type: [String, Number, Array],
  },
  apiUrl: {
    type: String,
    default: '',
  },
  apiParams: {
    type: Object,
    default: () => ({
      current: 1,
      size: 20,
    }),
  },
  // 搜索接口返回的数据中，option数组的key值
  optionsKey: {
    type: String,
    default: 'result',
  },
  // 远程搜索 接口传参对应的值
  searchParam: {
    type: String,
    default: 'codeOrName',
  },
  // 是否多选
  multiple: {
    type: Boolean,
    default: false,
  },
  // 选择框宽度
  width: {
    type: String,
  },
  // 传入的option数组中，要作为最终选择项的键值key（已废弃）
  valueCustom: {
    type: String,
    // default: 'itemCode',
    default: 'value',
  },
  // 传入的option数组中，要作为显示项的键值名称
  labelCustom: {
    type: String,
    default: 'label',
    // default: 'label',
  },

  // 小代码配置
  codeOption: {
    type: Object as PropType<CodeOption>,
    default: () => {
      return {
        codesetCode: '', // 代码分类编号
      }
    },
  },
  // 下拉框组件数据源
  options: {
    // type: Array as unknown as any[],
    type: Array as PropType<SelectItem[]>,
    default: () => [],
  },
  // 是否显示分页
  isShowPagination: {
    type: Boolean,
    default: false,
  },
  // 分页配置
  paginationOption: {
    type: Object,
    default: () => {
      return {
        pageSize: 6, // 每页显示条数
        currentPage: 1, // 当前页
        pagerCount: 5, // 按钮数，超过时会折叠
        total: 0, // 总条数
      }
    },
  },
  // 是否开启虚拟列表
  useVirtual: {
    type: Boolean,
    default: false,
  },
  // 是否启用分页
  usePagination: {
    type: Boolean,
    default: false, // 默认情况下不启用分页
  },
  // 是否开启搜索
  // showSearch: {
  //   type: Boolean,
  //   default: false,
  // },
  // 是否开启搜索
  searchable: {
    type: Boolean,
    default: false,
  },
  // 搜索关键词
  // keyWord: {
  //   type: String,
  //   default: '',
  // },
  // 搜索对象的属性的值，或集合
  displayKey: {
    type: [String, Array] as PropType<string | string[]>,
    default: 'label',
  },
  // searchKey: {
  //   type: [String, Array] as PropType<string | string[]>,
  //   default: 'label',
  // },
  props: {
    type: Object,
    default: () => ({}),
  },
  //禁止选
  disabled: {
    type: Boolean,
    default: false,
  },
  filterable: {
    type: Boolean,
    default: false,
  },
  filterMethod: {
    type: Function,
    default: null,
  },
  remote: {
    type: Boolean,
    default: false,
  },
  remoteMethod: {
    type: Function,
  },
  // 是否加载完毕
  loadMoreEnd: {
    type: Boolean,
    default: false,
  },
})

const slots = useSlots()
const autocompleteRef = ref(null)
// 抛出事件
const emits = defineEmits([
  'update:modelValue',
  'change',
  'eidt-change',
  'edit-change',
  'update:options',
  'update:loadMoreEnd',
  'load-more',
  'select',
])
const popperClassStr = computed(() => {
  let num = Math.floor(Math.random() * 1001)
  return `${selectProps.popperClass}-${route.name as string}` + num
})
const state = reactive({
  query: {
    current: 1,
    size: selectProps.apiParams?.size || 20,
  },
  dataList: [],
})
// vue3 v-model简写
let childSelectedValue: any = computed({
  get() {
    return selectProps.modelValue
  },
  set(val) {
    emits('update:modelValue', val)
  },
})
const loadMoreEndTemp = ref(selectProps.loadMoreEnd)
watch(
  () => selectProps.loadMoreEnd,
  (newValue) => {
    loadMoreEndTemp.value = newValue
  },
  { immediate: true, deep: true }
)
// 设置全选
const selectChecked = computed({
  get() {
    const _deval: any = selectProps.modelValue
    // return _deval?.length === selectProps.options.length
    return _deval?.length === optionsTemp.value.length
  },
  set(val: any) {
    // return val?.length === selectProps.options.length
    return val?.length === optionsTemp.value.length
  },
})

const keyword = ref('')
const changeValue = (e) => {
  if (Array.isArray(copyOptsData.value)) {
    optionsTemp.value = copyOptsData.value.filter((item) => {
      if (Array.isArray(selectProps.displayKey)) {
        return selectProps.displayKey.some((key) => item[key].includes(e))
      } else {
        return item[selectProps.displayKey].includes(e)
      }
    })
  } else {
    console.error('copyOptsData.value 不是一个有效的数组')
  }
}

const createFilter = (queryString: string) => {
  return (restaurant: any) => {
    const searchValue = queryString.toLowerCase()
    const keysToSearch = new Set<string>()

    // 添加props.valueKey到集合中
    if (Array.isArray(selectProps.displayKey) && selectProps.displayKey.length > 0) {
      selectProps.displayKey.forEach((key) => keysToSearch.add(key))
    } else {
      keysToSearch.add(selectProps.displayKey)
    }

    // if (props.valueKey) {
    //   keysToSearch.add(props.valueKey)
    // }
    // if (props.valueKey2) {
    //   keysToSearch.add(props.valueKey2)
    // }

    // // 如果props.valueKeyArr存在且不为空，将其内容添加到集合中
    // if (Array.isArray(props.valueKeyArr)) {
    //   props.valueKeyArr.forEach((key) => keysToSearch.add(key))
    // }

    // 遍历所有需要检查的key，判断是否匹配
    return Array.from(keysToSearch).some((key) => {
      return restaurant[key]?.toString().toLowerCase().includes(searchValue)
    })
  }
}
// 点击全选
const selectAll = (val: any) => {
  // const options = JSON.parse(JSON.stringify(selectProps.options))
  const optionsData = JSON.parse(JSON.stringify(optionsTemp.value))
  if (val) {
    const selectedAllValue = optionsData.map((item) => {
      // return item[selectProps.valueCustom]
      return item[optionsProps.value.value]
    })
    emits('update:modelValue', selectedAllValue)
  } else {
    emits('update:modelValue', null)
  }
}

// 是否使用小代码
const isCodeOption = computed(() => {
  return !!selectProps.codeOption.codesetCode
})
const optionsProps = ref<OptionsProps>({
  ...{
    value: isCodeOption.value ? 'itemCode' : 'value',
    label: isCodeOption.value ? 'itemCname' : 'label',
    disabled: 'disabled',
  },
  ...selectProps.props,
})

const optionsTemp = ref(selectProps.options)
// let optionsTemp: any = computed({
//   get() {
//     return selectProps.options
//   },
//   set(val) {
//     selectProps.options.value = val
//     emits('update:options', val)
//   },
// })
const copyOptsData = ref(JSON.parse(JSON.stringify(selectProps.options)))
watch(
  () => selectProps.options,
  (newValue, old) => {
    optionsTemp.value = newValue
    copyOptsData.value = newValue
  },
  { immediate: true, deep: true }
)
const handleChange = (e) => {
  emits('update:modelValue', e)
  emits('change', e)
  emits('eidt-change', e)
  emits('edit-change', e)
  const selectedOption = optionsTemp.value.find((item) => item[optionsProps.value.value] == e)
  emits('select', selectedOption)
}
const inintOptsData = (obj) => {
  apiQueryCodeitem(obj).then((res) => {
    if (res.data.success) {
      optionsTemp.value = res.data.data
      copyOptsData.value = JSON.parse(JSON.stringify(res.data.data))
    }
  })
}

// 监听小代码是否配置，如果配置了则从接口获取optionsData数据
watch(
  () => isCodeOption.value,
  (newValue) => {
    if (newValue) {
      inintOptsData(selectProps.codeOption)
    }
  },
  { immediate: true, deep: true }
)
// 远程搜索回调
const customRemoteMethod = (e) => {
  state.query.current = 1
  state.query = { ...state.query, ...selectProps.apiParams }
  state.query[selectProps.searchParam] = e
  optionsTemp.value = []
  loadMore()
}
const handleScroll = _.debounce((e) => {
  const { scrollTop, scrollHeight, clientHeight } = e.target
  if (scrollTop + clientHeight >= scrollHeight - 10) {
    emits('load-more')
    if (selectProps.usePagination && selectProps.apiUrl) {
      loadMore('more')
    }
  }
}, 300)
const loadMore = (type?: string, columnsVal?: any) => {
  if (loadMoreEndTemp.value && state.query.current > 1) return
  if (type === 'more') state.query.current++
  apiRequestPost(selectProps.apiUrl, state.query)
    .then((res) => {
      loadMoreEndTemp.value = false
      if (res.data.success) {
        if (type === 'more') {
          const newData = res.data.data[selectProps.optionsKey]
          state.dataList = [...state.dataList, ...newData]
          if (state.query.current * state.query.size >= res.data.data.count) {
            loadMoreEndTemp.value = true
          }
        } else {
          state.dataList = res.data.data[selectProps.optionsKey]
        }
        optionsTemp.value = state.dataList
        if (state.query.current * state.query.size >= res.data.data.count) {
          loadMoreEndTemp.value = true
        }
      }
    })
    .catch((error: any) => {
      // emits('update:loadMoreEnd', true)
    })
}

onMounted(() => {
  // 如果启动分页，则监听滚动事件
  if (selectProps.usePagination) {
    const autocomplete = document.querySelector(`.${popperClassStr.value} .el-select-dropdown__wrap`)
    if (autocomplete) {
      autocomplete.addEventListener('scroll', handleScroll)
    }
  }
})
onUnmounted(() => {
  if (selectProps.usePagination) {
    const autocomplete = document.querySelector(`.${popperClassStr.value} .el-select-dropdown__wrap`)
    // 检查事件处理器是否存在
    if (handleScroll && autocomplete) {
      autocomplete.removeEventListener('scroll', handleScroll)
    }
  }
})
</script>
<style lang="scss" scoped>
// .t_select {
.el-select-dropdown {
  .all_checkbox {
    margin-left: 20px;
  }
  .el-select-dropdown__item {
    margin: 0 5px;
  }
  .el-divider--horizontal {
    margin: 5px 0;
  }
  .el-input,
  .el-pagination {
    padding: 0 5px;
  }
}
.t_select__wrap {
  position: sticky;
  padding-top: 5px;
  top: 0px;
  left: 0px;
  background: #fff;
  z-index: 999;
}
.fi_select__bottom-loading {
  width: 100%;
  text-align: center;
  font-size: 20px;
  .fi_select__bottom-loading-text {
    color: #999;
    font-size: 12px;
  }
}
// }
</style>
